﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Power.Common
{
    public class AnchorPoint
    {
        public int Index { get; set; }
        /// <summary>
        /// X坐标
        /// 中心点坐标或者说控制点坐标，所有线的端点坐标为该坐标的需要联动
        /// </summary>
        public double X { get; set; }

        /// <summary>
        /// Y坐标
        /// 中心点坐标或者说控制点坐标，所有线的端点坐标为该坐标的需要联动
        /// </summary>
        public double Y { get; set; }

        /// <summary>
        /// 宽度
        /// </summary>
        public double Width { get; set; }

        /// <summary>
        /// 高度
        /// </summary>
        public double Height { get; set; }

        /// <summary>
        /// 鼠标形状
        /// </summary>
        public Cursor Cursor { get; set; }

        public Rectangle Rect { get; set; }

        /// <summary>
        /// 默认构造器
        /// </summary>
        public AnchorPoint()
        {

        }

        /// <summary>
        /// 带参数的构造器
        /// </summary>
        /// <param name="X">X</param>
        /// <param name="y">Y</param>
        /// <param name="cursor">鼠标</param>
        public AnchorPoint(double x, double y, int index)
        {
            this.X = x;
            this.Y = y;
            this.Width = 8;
            this.Height = 8;
            this.Index = index;
            

            double offset = this.Width / 2;
            this.Rect = new Rectangle()
            {
                Margin = new Thickness(this.X - offset, this.Y - offset, 0, 0),
                Width = this.Width,
                Height = this.Height,
                Fill = Brushes.LightGoldenrodYellow,
                Stroke = Brushes.Black,
                StrokeThickness = 1,
                Tag = index,
            };
        }


        public void Move(double x, double y)
        {
            double offset = this.Width / 2;
            this.Rect.Margin = new Thickness(x - offset, y - offset, 0, 0);
            this.X = x;
            this.Y = y;
        }

        public void Move()
        {
            double offset = this.Width / 2;
            this.Rect.Margin = new Thickness(X - offset, Y - offset, 0, 0);
        }
    }
    public class VarRectangle
    {
        /// <summary>
        /// 是否能改变
        /// </summary>
        public bool IsChange { get; set; }
        /// <summary>
        /// 画布
        /// </summary>
        private Canvas canvas;
        /// <summary>
        /// 直线
        /// </summary>
        private List<Line> lines = new List<Line>();

        /// <summary>
        /// 定位点
        /// </summary>
        public List<AnchorPoint> anchorPoints = new List<AnchorPoint>();
        private bool isMove = false;
        private bool isPointMove = false;
        private Point OldPoint = new Point();
        private AnchorPoint CurrentPoint = new AnchorPoint();
        public VarRectangle(Canvas canvas, string postion)
        {
            
            this.canvas = canvas;
            canvas.Children.Clear();
            
            double minX = 10;
            double maxX = 100;
            double minY = 10;
            double maxY = 100;
            if(!string.IsNullOrEmpty(postion))
            {
                var array = postion.Split(',');
                if (array.Length == 4)
                {
                    double.TryParse(array[0], out minX);
                    double.TryParse(array[1], out maxX);
                    double.TryParse(array[2], out minY);
                    double.TryParse(array[3], out maxY);
                }
            }
            

            anchorPoints.Add(new AnchorPoint(minX, minY, 0));
            anchorPoints.Add(new AnchorPoint(maxX, minY, 1));
            anchorPoints.Add(new AnchorPoint(maxX, maxY, 2));
            anchorPoints.Add(new AnchorPoint(minX, maxY, 3));

            lines.Add(new Line()
            {
                X1 = anchorPoints.Single(p => p.Index == 0).X,
                Y1 = anchorPoints.Single(p => p.Index == 0).Y,
                X2 = anchorPoints.Single(p => p.Index == 1).X,
                Y2 = anchorPoints.Single(p => p.Index == 1).Y,
                StrokeThickness = 2,
                Stroke = Brushes.Red,
                Tag = 0
            });

            lines.Add(new Line()
            {
                X1 = anchorPoints.Single(p => p.Index == 1).X,
                Y1 = anchorPoints.Single(p => p.Index == 1).Y,
                X2 = anchorPoints.Single(p => p.Index == 2).X,
                Y2 = anchorPoints.Single(p => p.Index == 2).Y,
                StrokeThickness = 2,
                Stroke = Brushes.Red,
                Tag = 1
            });

            lines.Add(new Line()
            {
                X1 = anchorPoints.Single(p => p.Index == 2).X,
                Y1 = anchorPoints.Single(p => p.Index == 2).Y,
                X2 = anchorPoints.Single(p => p.Index == 3).X,
                Y2 = anchorPoints.Single(p => p.Index == 3).Y,
                StrokeThickness = 2,
                Stroke = Brushes.Red,
                Tag = 2
            });


            lines.Add(new Line()
            {
                X1 = anchorPoints.Single(p => p.Index == 0).X,
                Y1 = anchorPoints.Single(p => p.Index == 0).Y,
                X2 = anchorPoints.Single(p => p.Index == 3).X,
                Y2 = anchorPoints.Single(p => p.Index == 3).Y,
                StrokeThickness = 2,
                Stroke = Brushes.Red,
                Tag = 3
            });

            Draw();
        }

        private void Draw()
        {

            foreach (var item in lines)
            {
                canvas.Children.Add(item);
            }

            foreach (var item in anchorPoints)
            {
                canvas.Children.Add(item.Rect);
            }


        }

        public void BindEvent()
        {
            IsChange = true;
            foreach (var item in anchorPoints)
            {
                item.Rect.MouseLeftButtonDown += Rect_MouseLeftButtonDown;
                item.Rect.Visibility = Visibility.Visible;
                switch (item.Index)
                {

                    case 0:
                    case 2:
                        item.Rect.Cursor = Cursors.SizeNWSE;
                        break;
                    case 1:
                    case 3:
                        item.Rect.Cursor = Cursors.SizeNESW;
                        break;
                }
            }

            canvas.MouseLeftButtonDown += Canvas_MouseLeftButtonDown;
            canvas.MouseMove += Canvas_MouseMove;
            canvas.MouseLeftButtonUp += Canvas_MouseLeftButtonUp;
        }
        public void UnBindEvent()
        {
            IsChange = false;
            foreach (var item in anchorPoints)
            {
                item.Rect.MouseLeftButtonDown -= Rect_MouseLeftButtonDown;
                item.Rect.Cursor = Cursors.Arrow;
                item.Rect.Visibility =  Visibility.Hidden;
            }

            canvas.MouseLeftButtonDown -= Canvas_MouseLeftButtonDown;
            canvas.MouseMove -= Canvas_MouseMove;
            canvas.MouseLeftButtonUp -= Canvas_MouseLeftButtonUp;
        }
        /// <summary>
        /// 获取坐标（xMin,xMax,yMin,yMax）
        /// </summary>
        /// <returns></returns>
        public string GetPostion()
        {
            double minX = anchorPoints.Min(o => o.X);
            double maxX = anchorPoints.Max(o => o.X);
            double minY = anchorPoints.Min(o => o.Y);
            double maxY = anchorPoints.Max(o => o.Y);

            return $"{minX},{maxX},{minY},{maxY}";
        }
        private void Canvas_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            isPointMove = false;
            isMove = false;
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {

            var point = e.GetPosition(canvas);

            double minX = anchorPoints.Min(o => o.X);
            double maxX = anchorPoints.Max(o => o.X);
            double minY = anchorPoints.Min(o => o.Y);
            double maxY = anchorPoints.Max(o => o.Y);

            if (point.X > minX && point.X < maxX && point.Y > minY && point.Y < maxY)
            {
                Mouse.SetCursor(Cursors.Hand);
            }
            else
            {
                Mouse.SetCursor(Cursors.Arrow);
            }

            if (isMove)
            {


                foreach (var item in anchorPoints)
                {
                    item.Move(item.X + point.X - OldPoint.X, item.Y + point.Y - OldPoint.Y);
                }

                ReDrawLines();

                OldPoint = point;
            }


            if (isPointMove)
            {
                var index = CurrentPoint.Index;
                var pointX = anchorPoints.Single(p => p.Index != index && p.X == CurrentPoint.X);
                var pointY = anchorPoints.Single(p => p.Index != index && p.Y == CurrentPoint.Y);

                CurrentPoint.Move(point.X, point.Y);
                pointX.Move(point.X, pointX.Y);
                pointY.Move(pointY.X, point.Y);

                ReDrawLines();
            }
        }

        private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            OldPoint = e.GetPosition(canvas);

            double minX = anchorPoints.Min(o => o.X);
            double maxX = anchorPoints.Max(o => o.X);
            double minY = anchorPoints.Min(o => o.Y);
            double maxY = anchorPoints.Max(o => o.Y);

            if (OldPoint.X > minX && OldPoint.X < maxX && OldPoint.Y > minY && OldPoint.Y < maxY)
            {
                isMove = true;
            }
        }

        public void ReDrawLines()
        {
            foreach (var item in lines)
            {
                var index = (int)item.Tag;
                switch (index)
                {
                    case 0:
                        item.X1 = anchorPoints.Single(p => p.Index == 0).X;
                        item.Y1 = anchorPoints.Single(p => p.Index == 0).Y;
                        item.X2 = anchorPoints.Single(p => p.Index == 1).X;
                        item.Y2 = anchorPoints.Single(p => p.Index == 1).Y;
                        break;
                    case 1:
                        item.X1 = anchorPoints.Single(p => p.Index == 1).X;
                        item.Y1 = anchorPoints.Single(p => p.Index == 1).Y;
                        item.X2 = anchorPoints.Single(p => p.Index == 2).X;
                        item.Y2 = anchorPoints.Single(p => p.Index == 2).Y;
                        break;
                    case 2:
                        item.X1 = anchorPoints.Single(p => p.Index == 2).X;
                        item.Y1 = anchorPoints.Single(p => p.Index == 2).Y;
                        item.X2 = anchorPoints.Single(p => p.Index == 3).X;
                        item.Y2 = anchorPoints.Single(p => p.Index == 3).Y;
                        break;
                    case 3:
                        item.X1 = anchorPoints.Single(p => p.Index == 0).X;
                        item.Y1 = anchorPoints.Single(p => p.Index == 0).Y;
                        item.X2 = anchorPoints.Single(p => p.Index == 3).X;
                        item.Y2 = anchorPoints.Single(p => p.Index == 3).Y;
                        break;
                }
            }
        }
        private void Rect_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            isPointMove = false;
        }

        private void Rect_MouseMove(object sender, MouseEventArgs e)
        {
            Rectangle rect = (Rectangle)sender;
            if (isPointMove)
            {
                var index = (int)rect.Tag;
                var point = e.GetPosition(canvas);
                var currentPoint = anchorPoints.Single(p => p.Index == index);
                var pointX = anchorPoints.Single(p => p.Index != index && p.X == currentPoint.X);
                var pointY = anchorPoints.Single(p => p.Index != index && p.Y == currentPoint.Y);

                currentPoint.Move(point.X, point.Y);
                pointX.Move(point.X, pointX.Y);
                pointY.Move(pointY.X, point.Y);

                ReDrawLines();
            }
        }

        private void Rect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Rectangle rect = (Rectangle)sender;
            Mouse.SetCursor(rect.Cursor);
            isPointMove = true;
            var index = (int)rect.Tag;
            CurrentPoint = anchorPoints.Single(p => p.Index == index);

        }


    }
}
